package alpha.com.google.code.mechanic.janitor.ui;

import java.io.File;
import java.io.IOException;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import alpha.com.google.code.mechanic.janitor.controller.ContextData;
import alpha.com.google.code.mechanic.janitor.controller.MechanicTaskSource;
import alpha.com.google.code.mechanic.janitor.controller.UnZipFiles;
import alpha.com.google.code.mechanic.janitor.model.DefaultSysFilePath;
import alpha.com.google.code.mechanic.janitor.model.IContext;
import alpha.com.google.code.mechanic.janitor.model.ProjectContext;

/**
 * The class is to create a dialog that allows users to import a set of
 * configurations of a Context, and the users can also specify whether to
 * activated the Context at the same time. 
 * 
 * Last_edited: Nov 6, 2014
 *
 * @History
 * 1. Change the method used to save the Contexts information to context.con
 * file.
 * @author jingjiejiang
 * @edited Nov 3, 2014
 * 1) In the method addNewCtxToList(), use the method SaveContextsInfo() of
 * ContextData to replace the method serializeContextsInfo(File file) of
 * ContextsCollector
 * 
 * 2. 
 * @author jingjiejiang
 * @edited Nov 6, 2014
 * 1) Add a private filed: ContextData ctxData.
 * 2) Check Context name duplicationw when editing txtNewCtxName.
 * 
 * @author jingjiejiang
 * @since Oct 31, 2014
 */
public class ImportContextDialog extends Dialog {
  
  private static final String IMPORT_CONTEXT_DIALOG_TITLE = "Import Cpontext Settings";
  
  private Button btnActivateCtx;
  
  private Text txtSrcZipFile;
  private Text txtNewCtxName;
  private boolean isActivate;
  private ContextData ctxData;

  /**
   * Create the dialog.
   * @param parentShell
   */
  public ImportContextDialog(Shell parentShell) {
    super(parentShell);
    isActivate = false;
    ctxData = new ContextData();
    try {
      ctxData.readContextsFile();
    } catch (Exception e) {
      MessageDialog.openError(getParentShell(), "Couldn't read the "
          + "context.con file.", e.getMessage());
    }
  }
  
  @Override
  public void create() {
    super.create();
    getButton(IDialogConstants.OK_ID).setEnabled(false);
  }

  @Override
  public void configureShell(Shell shell) {
    super.configureShell(shell);
    if (IMPORT_CONTEXT_DIALOG_TITLE != null) {
      shell.setText(IMPORT_CONTEXT_DIALOG_TITLE);
    }
  }
  
  /**
   * Create contents of the dialog.
   * @param parent
   */
  @Override
  protected Control createDialogArea(Composite parent) {
    Composite container = (Composite) super.createDialogArea(parent);
    
    Composite composite = new Composite(container, SWT.NONE);
    GridData gd_composite = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
    gd_composite.heightHint = 101;
    gd_composite.widthHint = 384;
    composite.setLayoutData(gd_composite);
    
    Label lblNewLabel = new Label(composite, SWT.NONE);
    lblNewLabel.setBounds(0, 7, 84, 14);
    lblNewLabel.setText("From *.zip file:");
    
    txtSrcZipFile = new Text(composite, SWT.BORDER);
    txtSrcZipFile.setBounds(90, 4, 249, 19);
    
    initBtnBrowseZipFile(composite);
    
    Label lblNewCtxName = new Label(composite, SWT.NONE);
    lblNewCtxName.setBounds(0, 47, 109, 14);
    lblNewCtxName.setText("New Context name:");
    
    txtNewCtxName = new Text(composite, SWT.BORDER);
    txtNewCtxName.addModifyListener(new ModifyListener() {
      public void modifyText(ModifyEvent e) {
        
        boolean isenable = false;
        
        if (txtNewCtxName.getText().equals("")) {
        }
        else {
          if (ctxData.getContextsCollector().isValidCtxName(
              txtNewCtxName.getText())) {
            isenable = true;
          }
          else {
            MessageDialog.openError(getParentShell(), "Error", "There "
                + "already exist a Context with the same name. Please "
                + "specify another name for the new Context."); 
          }
        }
        
        getButton(IDialogConstants.OK_ID).setEnabled(isenable);
      }
    });
    txtNewCtxName.setBounds(121, 44, 263, 19);
    
    initBtnActivateCtx(composite);
    
    Label label = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
    label.setBounds(0, 34, 384, 2);

    return container;
  }
  
  private void initBtnBrowseZipFile (Composite composite) {
    
    Button btnBrowseZipFile = new Button(composite, SWT.NONE);
    btnBrowseZipFile.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        
        FileDialog dialog = new FileDialog(getParentShell());
        String file = dialog.open();
        txtSrcZipFile.setText(file);
        
        setTxtNewCtxName(file);
        
      }
    });
    btnBrowseZipFile.setBounds(341, 0, 43, 28);
    btnBrowseZipFile.setText("...");
  }
  
  private void setTxtNewCtxName(String path) {
    
    txtNewCtxName.setText("");
    
    String[] elements = path.split(File.separator);
    for (String string : elements) {
      if (string.contains(".zip")) {
        int index = string.indexOf(".zip");
        txtNewCtxName.setText(string.substring(0, index));
      }
    }
  }
  
  private void initBtnActivateCtx (Composite composite) {
  
    btnActivateCtx = new Button(composite, SWT.RADIO);
    btnActivateCtx.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        
        isActivate = !isActivate;
        btnActivateCtx.setSelection(isActivate);
      }
    });
    btnActivateCtx.setBounds(0, 77, 166, 18);
    btnActivateCtx.setText("Activate the new Context");
  }

  /**
   * Create contents of the button bar.
   * @param parent
   */
  @Override
  protected void createButtonsForButtonBar(Composite parent) {
    createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
        true);
    createButton(parent, IDialogConstants.CANCEL_ID,
        IDialogConstants.CANCEL_LABEL, false);
  }

  /**
   * Return the initial size of the dialog.
   */
  @Override
  protected Point getInitialSize() {
    return new Point(404, 187);
  }
  
  @Override
  protected void okPressed() {
    
    IContext context = generateNewContext(txtNewCtxName.getText());
    if (context != null) {
      addNewCtxToList(context);
      MessageDialog.openInformation(getParentShell(), "Information", "The "
          + "new context has been added to the Workspace Janitor.");
    }

    super.okPressed();
  }
  
  /**
   * The method is to decompress the selected zip file to a specified
   * directory.
   *
   * @param dstnFile The directory where the decompressed files should be put.
   * @return <code>true</code>return true if it succeeds;
   *         <code>false</code>return false if it does not succeed.
   */
  private boolean unZipSelFile (String dstnFile) {
        
    UnZipFiles zip = new UnZipFiles(txtSrcZipFile.getText(),
        dstnFile);
    return zip.decompressZipFile();
  }
  
  private IContext generateNewContext(String ctxName) {
    
    DefaultSysFilePath syspath = new DefaultSysFilePath();
    
    syspath.initCtxFileDir();
    
    String ctxdir = syspath.getDefaultSysFilePath() + ctxName;
    if (unZipSelFile(ctxdir)) {
      
      String ctxlocation = ctxdir;

      // Currently, just create a new object of ProjectContext, in the
      // the future, it may needs to create other types of Context.
      return new ProjectContext(ctxName, ctxlocation);
    } else {
      return null;
    }
  }
  
  /**
   * The method is to add the "context" to the current Context list of the
   * Workspace Janitor and write the changes back to the context.con file.
   * 
   * @param context The Context that will be added.
   */
  private void addNewCtxToList(IContext context) {
    
    if (true == btnActivateCtx.getSelection()) {
      context.setSelected(true);
      ctxData.getContextsCollector().addContext(context);
      
      if (false == addCtxToTaskSrc(context)) {
        
        MessageDialog.openError(getParentShell(), "Error", "Couldn't activate"
            + " the new Context in the Worksoace Janitor.");
        return;
      }
      
    } else {
      
      ctxData.getContextsCollector().addContext(context);
    }
    
    try {
      ctxData.saveContextsInfo();
    } catch (IOException e) {
      MessageDialog.openError(getParentShell(), "Couldn't save the changes"
          + " to the context.con file.", e.getMessage());
    }

  }
  
  /**
   * The method is to add the "context" location to the "task source".
   *
   * @param context The Context that will be added to the task source.
   * @return <code>true</code>return true if it succeeds;
   *         <code>false</code>return false if it does not succeed.
   */
  private boolean addCtxToTaskSrc(IContext context) {
    
    MechanicTaskSource source = new MechanicTaskSource();
    return source.addDirectoryToTaskSrc(context.getFileLocation());
  }
  
}
